条件分岐 ~ [[ で条件判定(正規表現)

[[ 文字列 ~= 正規表現 ]] パターンマッチ

複合コマンド [[ では =~ 演算子で拡張正規表現でのパターンマッチを行うことができます。

code
  if [[ 2023-01-02 =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2})$ ]]; then
    echo "マッチしました"
  fi
stdout
マッチしました

左辺の文字列が右辺の正規表現にマッチした場合の結果は 0 で、マッチしなかった場合の結果は 1 になります。また右辺の正規表現が文法的に間違っている場合の結果は 2 になります。

code
[[ apple =~ ^apple$ ]]
echo "結果=$? : マッチした場合"

[[ apple =~ ^app$ ]]
echo "結果=$? : マッチしなかった場合"

[[ apple =~ []{} ]]
echo "結果=$? : 文法的に間違っている場合"
stdout
結果=0 : マッチした場合
結果=1 : マッチしなかった場合
結果=2 : 文法的に間違っている場合

マッチしたパターンは BASH_REMATCH に格納されます。BASH_REMATCH は配列で 0 番目にはマッチした文字列がすべて格納されます。1 ~ は キャプチャされたパターンが設定されます。

code
[[ 2023-01-02 =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2})$ ]]
echo "BASH_REMATCH[0] = ${BASH_REMATCH[0]}"
echo "BASH_REMATCH[1] = ${BASH_REMATCH[1]}"
echo "BASH_REMATCH[2] = ${BASH_REMATCH[2]}"
echo "BASH_REMATCH[3] = ${BASH_REMATCH[3]}"
stdout
BASH_REMATCH[0] = 2023-01-02
BASH_REMATCH[1] = 2023
BASH_REMATCH[2] = 01
BASH_REMATCH[3] = 02

以下は BASH_REMATCH を使用して文字列を置換するサンプルです。

code
# BASH_REMATCHを使って文字列置換
str=東京都

[[ ${str} =~ ^(.+?)(都|道|府|県)$ ]]
echo "${BASH_REMATCH[@]}"

str="${BASH_REMATCH[1]}駅"
echo "${str}"
stdout
東京都 東京 都
東京駅

パターンをクォートで囲んだ場合、正規表現としてではなく文字列としてマッチングが行われます。

code
[[ 2023-01-02 =~ "^([0-9]{4})-([0-9]{2})-([0-9]{2})$" ]]
echo "結果=$? BASH_REMATCH=${BASH_REMATCH[@]}"

[[ 2023-01-02 =~ "2023-01-02" ]]
echo "結果=$? BASH_REMATCH=${BASH_REMATCH[@]}"
stdout
結果=1 BASH_REMATCH=
結果=0 BASH_REMATCH=2023-01-02

変数に設定されているパターンでマッチングを行うこともできます。この場合もクォートで囲んだ場合、正規表現としてではなく文字列としてマッチングが行われます。

code
pattern='^([0-9]{4})-([0-9]{2})-([0-9]{2})$'

[[ 2023-01-02 =~ "${pattern}" ]]
echo "結果=$? BASH_REMATCH=${BASH_REMATCH[@]}"

[[ 2023-01-02 =~ ${pattern} ]]
echo "結果=$? BASH_REMATCH=${BASH_REMATCH[@]}"
stdout
結果=1 BASH_REMATCH=
結果=0 BASH_REMATCH=2023-01-02 2023 01 02

パターンの正規表現は拡張正規表現のため \s や \w、\d のような Perlの正規表現は使用できません。

code
str='123 '

# \d, \s などは使用できないのでマッチしない
[[ ${str} =~ ^\d+\s*$ ]]
echo "結果=$?"

# これらはマッチする
# 正規表現でスペースを使う場合はエスケープかクォートが必要
[[ ${str} =~ ^[[:digit:]]+[[:space:]]*$ ]]
echo "結果=$?"
[[ ${str} =~ ^[0-9]+\ *$ ]]
echo "結果=$?"
[[ ${str} =~ ^[0-9]+' '*$ ]]
echo "結果=$?"
stdout
結果=1
結果=0
結果=0
結果=0
code
str=$'1\n2\n3'

# このような指定方法で改行にマッチさせることができる
[[ ${str} =~ ^1$'\n'2$'\n'3$ ]]
echo "結果=$?"
# [[:space:]]は[ \t\n\r\f\v]にマッチ
[[ ${str} =~ ^1[[:space:]]2[[:space:]]3$ ]]
echo "結果=$?"
stdout
結果=0
結果=0